# coding: utf-8
from typing import Dict, List

from PySide6.QtCore import QPoint, Qt, QThreadPool
from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout
from loguru import logger
from qfluentwidgets import TransparentPushButton, FluentIcon as FIF, Action, FluentIcon
from qfluentwidgets.components.material import AcrylicMenu

from common import Icon, signalBus, Task, TaskMessage, TaskStatus, TaskDao
from components import ListWidget, TaskCard, Alert
from components.dialog import AddLinkDialog, AddM3u8Dialog
from threads import StreamRunner, M3u8Runner, send_sql_request


class TaskInterface(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.verticalLayout = QVBoxLayout(self)
        self.horizontalLayout = QHBoxLayout()
        self.addBtn = TransparentPushButton(FIF.ADD, '添加任务', self)
        self.statusBtn = TransparentPushButton(FIF.PLAY, '全部开始', self)
        self.stopBtn = TransparentPushButton(FIF.PAUSE, '全部停止', self)
        self.listWidget = ListWidget(self)
        self.pool = QThreadPool(self)
        self.task_dict = {}  # type: Dict[str, TaskCard]

        self.__initWidgets()
        self.__connectSignals()
        self.initHistoryTasks()

    def __initWidgets(self):
        self.setObjectName("TaskInterface")
        self.pool.setMaxThreadCount(3)

        self.horizontalLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)
        self.horizontalLayout.addWidget(self.addBtn)
        self.horizontalLayout.addWidget(self.statusBtn)
        self.horizontalLayout.addWidget(self.stopBtn)
        self.verticalLayout.addLayout(self.horizontalLayout, 0)
        self.verticalLayout.addWidget(self.listWidget)

    def __connectSignals(self):
        self.addBtn.clicked.connect(self.onAddBtnClicked)
        self.statusBtn.clicked.connect(self.startAllTasks)
        self.stopBtn.clicked.connect(self.stopAllTasks)

        signalBus.taskAddedSig.connect(self.onAddTask)
        signalBus.taskReAddSig.connect(self.pool.start)
        signalBus.clearCacheSig.connect(self.deleteAllTasks)
        signalBus.taskMsgSig.connect(self.onTaskMessage)

    def initHistoryTasks(self):
        def setInitTasks(tasks: List[Task]):
            for task in tasks:
                self.onAddTask(task, False)

        send_sql_request(TaskDao.get_all, slot=setInitTasks)

    def onAddBtnClicked(self):
        menu = AcrylicMenu(parent=self)
        menu.addAction(Action(Icon.LINK, '下载链接', self, triggered=self.showAddLinkDialog))
        menu.addAction(Action(FluentIcon.VIDEO, 'M3U8下载', self, triggered=self.showM3U8Dialog))

        x = self.addBtn.x() - 10
        pos = self.addBtn.mapToGlobal(QPoint(x, self.addBtn.height()))
        menu.exec(pos)

    def showAddLinkDialog(self):
        dialog = AddLinkDialog(self.window())
        dialog.exec()

    def showM3U8Dialog(self):
        dialog = AddM3u8Dialog(self.window())
        dialog.exec()

    def showTaskByStatus(self, status: TaskStatus = None):
        for i in range(self.listWidget.count()):
            item = self.listWidget.item(i)
            widget: TaskCard = self.listWidget.itemWidget(item)
            if widget.status == status or status is None:
                item.setHidden(False)
            else:
                item.setHidden(True)

    def onAddTask(self, task: Task, isRun=True):
        tp = task.type
        tid = task.id
        file_name = task.file_name
        if tp == 'Link':
            runner = StreamRunner(task)
        elif tp == 'M3U8':
            runner = M3u8Runner(task)
        else:
            logger.error(f'未知类型{tp}')
            return
        card = TaskCard(runner, self)
        card.deleteTaskSig.connect(self.onTaskDelete)
        card.setTask(task)
        card.setTitle(file_name)
        self.task_dict[tid] = card
        self.listWidget.addWidget(card)
        if isRun:
            self.pool.start(runner)
            Alert.success(f'添加{file_name}, {task.url}, 任务成功')

        send_sql_request(
            TaskDao.add,
            task
        )

    def onTaskMessage(self, taskMsg: TaskMessage):
        tid = taskMsg.id
        if tid not in self.task_dict:
            return
        card = self.task_dict[tid]
        card.setTaskMessage(taskMsg)

    def onTaskDelete(self, card: TaskCard):
        tid = card.task.id
        self.listWidget.removeWidget(card)
        del self.task_dict[tid]

    def startAllTasks(self):
        for card in self.task_dict.values():
            if card.status in [TaskStatus.PAUSE, TaskStatus.CANCEL]:
                card.start()

    def stopAllTasks(self):
        for card in self.task_dict.values():
            card.stop()

    def deleteAllTasks(self):
        self.stopAllTasks()
        self.listWidget.clear()
        self.task_dict.clear()
